package cz.proks.easyhelpdesk.gwt.ui.widget;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.CssResource.ImportedWithPrefix;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimpleLayoutPanel;

public class ErrorWidget extends SimpleLayoutPanel {
    
    public static interface Resources extends ClientBundle {
       
        @ImportedWithPrefix("easyhelpdesk-Error")
        interface Css extends CssResource {
            String DEFAULT_STYLE = "ErrorWidget.css";
            String panel();
            String errorMessage();
            String errorStackTrace();
        }
        
        @Source(Css.DEFAULT_STYLE)
        Css style();
    }

    
    private Throwable exception;
    
    private final DockLayoutPanel mainPanel = new DockLayoutPanel(Unit.EM);    
    private final Label messageLabel = new Label();
    private final HTMLPanel stackTracePanel = new HTMLPanel("");
    private final ScrollPanel stackTraceScrollPanel = new ScrollPanel();    
    
    
    private final Resources resources = GWT.create(Resources.class);
    
    public ErrorWidget() {
        // Set CSS styles        
        resources.style().ensureInjected();
                
        this.mainPanel.setStyleName(resources.style().panel());
        this.messageLabel.setStyleName(resources.style().errorMessage());
        this.stackTracePanel.setStyleName(resources.style().errorStackTrace());
    }
    
    public ErrorWidget(Throwable exception) {
        this();        
        this.exception = exception;                
        
        init();
    }
    
    private void init() {
        this.messageLabel.setText(SafeHtmlUtils.htmlEscapeAllowEntities(exception == null ? "Exception occurs" : exception.getMessage()));
        
        this.stackTracePanel.clear();
        this.stackTracePanel.add(new HTML(stackTraceToHtml(exception == null ? null : exception.getStackTrace())));
        
        this.stackTraceScrollPanel.setWidget(stackTracePanel);
                
        this.mainPanel.addNorth(messageLabel, 4);
        this.mainPanel.add(stackTraceScrollPanel);
        
        setWidget(mainPanel);                
    }
    
    @Override
    public void onResize() {        
        stackTraceScrollPanel.onResize();      
    }
    
    public void setException(Throwable exception) {
        this.exception = exception;
        init();        
    }
    
     
    public Label getMessageLabel() {
        return messageLabel;
    }
    
    public HTMLPanel getStackTracePanel() {
        return stackTracePanel;
    }            
            
    private SafeHtml stackTraceToHtml(StackTraceElement[] stackTraceElements) {
        SafeHtmlBuilder htmlBuilder = new SafeHtmlBuilder();
        
        if (stackTraceElements != null)
            for (StackTraceElement element : stackTraceElements) {                
                String elementStr = element.toString()
                                           .concat("\n")
                                           .replaceAll("\n", "<br>")
                                           .replaceAll("\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
                SafeHtml safeHtml = SafeHtmlUtils.fromTrustedString(elementStr);
                htmlBuilder.append(safeHtml);
            }
        
        return htmlBuilder.toSafeHtml();
    }      
}
